#include "mdescriptor.h"

MDescriptor::MDescriptor()
{
	PSVector=nullptr;
	AADVector=nullptr;
	SPRHVector=nullptr;
	UPFDVector=nullptr;
	FrontFDVector=nullptr;
	UPFDVector=nullptr;
	FrontARTVector=nullptr;
	D2Vector=nullptr;


	PSWeight=1;
	AADWeight=1;
	SPRHWeight=1;
	UPFDWeight=1;
	FrontFDWeight=1;
	UPARTWeight=1;
	FrontARTWeight=1;
	D2Weight=1;
	
	size=9;
}

MDescriptor::~MDescriptor() 
{
	if(PSVector!=nullptr)
		delete PSVector;
	if(AADVector!=nullptr)
		delete AADVector;
	if(SPRHVector!=nullptr)
		delete SPRHVector;
	if(UPFDVector!=nullptr)
		delete UPFDVector;
	if(FrontFDVector!=nullptr)
		delete FrontFDVector;
	if(UPARTVector!=nullptr)
		delete UPARTVector;
	if(FrontARTVector!=nullptr)
		delete FrontARTVector;
	if(D2Vector!=nullptr)
		delete D2Vector;
}

bool MDescriptor::ExtractVector( ifstream &in,int type)
{
	int dims=0,lines=0;
	bool flag=true;
	switch(type)
	{
	case PS:
		dims=63, lines=9;
		PSVector=new BYTE[PS_SIZE];
		flag=ExtractVector(in,dims,lines,PSVector);
		break;;
	case AAD:
		dims=64, lines=4;
		AADVector=new BYTE[AAD_SIZE];
		flag=ExtractVector(in,dims,lines,AADVector);
		break;
	case SPRH:
		dims=625,lines=1;
		SPRHVector=new BYTE[SPRH_SIZE];
		flag=ExtractVector(in,dims,lines,SPRHVector);
		break;
	case UPFD:
		dims=10,lines=1;
		UPFDVector=new BYTE[FD_SIZE];
		flag=ExtractVector(in,dims,lines,UPFDVector);
		break;
	case UPART:
		dims=35,lines=1;
		UPARTVector=new BYTE[ART_SIZE];
		flag=ExtractVector(in,dims,lines,UPARTVector);
		break;
	case FrontFD:
		dims=10,lines=1;
		FrontFDVector=new BYTE[FD_SIZE];
		flag=ExtractVector(in,dims,lines,FrontFDVector);
		break;
	case FrontART:
		dims=35,lines=1;
		FrontARTVector=new BYTE[ART_SIZE];
		flag=ExtractVector(in,dims,lines,FrontARTVector);
		break;
	case D2:
		dims=10,lines=1;
		D2Vector=new BYTE[D2_SIZE];
		flag=ExtractVector(in,dims,lines,D2Vector);
		break;
	default:
		return false;
	}
	return flag;
}

bool MDescriptor::ExtractVector( ifstream &in,int dims,int lines,BYTE* Ptr)
{
	string buffer;

	int index=0;
	for(int i=0;i<lines;++i)
	{
		getline(in,buffer);
		stringstream ss(buffer);
		string item;
		while(getline(ss,item,' '))
		{
			Ptr[index]=(BYTE)atoi(item.c_str());
			index++;
		}
		if(index%dims!=0)
			return false;
	}
	return true;
}

bool MDescriptor::ExtractModelDescriptor( string path )
{
	bool flag=true;
	for (int i=0;i<9;++i)
	{
		string destP;
		switch(i)
		{
		case PS:
			destP=path+".ps";
			break;
		case AAD:
			destP=path+".aad";
			break;
		case SPRH:
			destP=path+".sprh";
			break;
		case UPFD:
			destP=path+"UP.fd";
			break;
		case FrontFD:
			destP=path+"Front.fd";
			break;
		case UPART:
			destP=path+"UP.art";
			break;
		case FrontART:
			destP=path+"Front.art";
			break;
		case D2:
			destP=path+".d2";
			break;
		default:
			return false;
		}
		ifstream in(destP);
		flag=ExtractVector(in,i);
		in.close();
	}
	return flag;
}

vector<double> MDescriptor::operator-( MDescriptor& v2 )
{
	vector<double> distances(8,0.0);

	distances[0]=PSWeight*CalculateDistance(PSVector,v2.PSVector,PS_SIZE);
	distances[1]=AADWeight*CalculateDistance(AADVector,v2.AADVector,AAD_SIZE);
	distances[2]=SPRHWeight*CalculateDistance(SPRHVector,v2.SPRHVector,SPRH_SIZE);
	distances[3]=UPFDWeight*CalculateDistance(UPFDVector,v2.UPFDVector,FD_SIZE);
	distances[4]=FrontFDWeight*CalculateDistance(FrontFDVector,v2.FrontFDVector,FD_SIZE);
	distances[5]=UPARTWeight*CalculateDistance(UPARTVector,v2.UPARTVector,ART_SIZE);
	distances[6]=FrontARTWeight*CalculateDistance(FrontARTVector,v2.FrontARTVector,ART_SIZE);
	distances[7]=D2Weight*CalculateDistance(D2Vector,v2.D2Vector,D2_SIZE);

	return distances;
}

float MDescriptor::CalculateDistance( BYTE* Ptr,BYTE*Ptr2,int dims )
{
	float distance=0;
	for (int i=0;i<dims;++i)
	{
		//distance+=abs(Ptr[i]-Ptr2[i]);
		distance+=(Ptr[i]-Ptr2[i])*(Ptr[i]-Ptr2[i]);
	}
	distance/=dims;

	return sqrt(distance);
}

